package puzzle.projecteuler.p100;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class Problem061 {

	/**
	 * @param args
	 */
	@SuppressWarnings("unchecked")
	public static void main(String[] args) {

		List<Integer> ps3 = ps(3);
		List<Integer> ps4 = ps(4);
		List<Integer> ps5 = ps(5);
		List<Integer> ps6 = ps(6);
		List<Integer> ps7 = ps(7);
		List<Integer> ps8 = ps(8);
		Map<Integer, List<Integer>> tmp = mergeToMap(ps3, ps4, ps5, ps6, ps7, ps8);
		Set<Integer> ns = tmp.keySet();
		for (Integer p1: ns) {
			for (Integer p2: ns) {
				if (check(p1, p2)) {
					for (Integer p3: ns) {
						if (check(p2, p3)) {
							for (Integer p4: ns) {
								if (check(p3, p4)) {
									for (Integer p5: ns) {
										if (check(p4, p5)) {
											for (Integer p6: ns) {
												if (check(p5, p6) && check(p6, p1)){
													Integer[] t = check(tmp.get(p1), tmp.get(p2), tmp.get(p3), tmp.get(p4), tmp.get(p5), tmp.get(p6));
													if (t != null) {
														System.out.println(p1+p2+p3+p4+p5+p6 + ":" + p1+"("+t[0]+"),"+p2+"("+t[1]+"),"+p3+"("+t[2]+"),"+p4+"("+t[3]+"),"+p5+"("+t[4]+"),"+p6 + "("+t[5]+")");
													}
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
	}

	/**
	 * 能否从六个列表中，每个列表取出一个数来，得到的六个数互不相同
	 * @param l1
	 * @param l2
	 * @param l3
	 * @param l4
	 * @param l5
	 * @param l6
	 * @return
	 */
	private static Integer[] check(List<Integer> l1, List<Integer> l2,
			List<Integer> l3, List<Integer> l4, List<Integer> l5,
			List<Integer> l6) {
		for (int a1: l1) {
			for (int a2: l2) {
				if (a2 != a1) {
					for (int a3: l3) {
						if (a3 != a2 && a3 != a1) {
							for (int a4: l4) {
								if (a4 != a3 && a4 != a2 && a4 != a1) {
									for (int a5: l5) {
										if (a5 != a4 && a5 != a3 && a5 != a2 && a5 != a1) {
											for (int a6: l6) {
												if (a6 != a5 && a6 != a4 && a6 != a3 && a6 != a2 && a6 != a1) {
													return new Integer[] {a1,a2,a3,a4,a5,a6};
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
		return null;
	}

	public static int p(int style, int n) {
		
		switch (style) {
		case 3: return n*(n+1)/2;
		case 4: return n*n;
		case 5: return n*(3*n-1)/2;
		case 6: return n*(2*n-1);
		case 7: return n*(5*n-3)/2;
		case 8: return n*(3*n-2);
		}
		return -1;
	}
	
	public static List<Integer> ps(int style) {
		
		List<Integer> ps = new ArrayList<Integer>();
		int n = 1;
		int p = 0;
		while (true) {
			n ++;
			p = p(style, n);
			if (p < 1000) {
				continue;
			} else if (p > 10000) {
				break;
			} else {
				ps.add(p);
			}
		}
		return ps;
	}
	
	public static boolean check(int a, int b) {
		return (a%100) == (b/100);
	}

	public static Map<Integer, List<Integer>> mergeToMap(List<Integer>... as) {
		
		Map<Integer, List<Integer>> tmp = new HashMap<Integer, List<Integer>>();
		for (int i = 0; i < as.length; i ++) {
			List<Integer> a = as[i];
			int m = i+3;
			for (Integer n: a) {
				if (tmp.get(n) == null) {
					tmp.put(n, new ArrayList<Integer>());
				}
				tmp.get(n).add(m);
			}
		}
		return tmp;
	}
	
	public static Set<Integer> mergeToSet(List<Integer>... as) {
		
		Set<Integer> tmp = new HashSet<Integer>();
		for (List<Integer> a: as) {
			for (Integer n: a) {
				tmp.add(n);
			}
		}
		return tmp;
	}
}
